package com.collabscm.tools.ant;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Concat;
import org.apache.tools.ant.types.FileList;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

/**
 * 资源文件合并
 *
 * @author Zeng Raoxing
 */
public class ResourceConcat extends Task {
	/**
	 * 配置文件
	 */
	private String configFile;
	/**
	 * 根目录
	 */
	private File baseDir;
	/**
	 * 文件扩展名格式
	 */
	private SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmm");
	
	public void setConfigFile(String configFile) {
		this.configFile = configFile;
	}

	public void setBaseDir(File baseDir) {
		this.baseDir = baseDir;
	}

	public void execute() throws BuildException {
		ConfigFile config;
		try {
			config = parseConfigFile();
		} catch (Exception e) {
			throw new BuildException(e);
		}
		for(ConcatFile concat : config.concats) {
			concat(concat, config.context, config.extension);
		}
    }
	
	private ConfigFile parseConfigFile() throws Exception {
		Serializer serializer = new Persister();
		File file = new File(configFile);
		return serializer.read(ConfigFile.class, file);
	}
	
	private void concat(ConcatFile concatFile, String context, String ext) {
		//ANT的concat命令
		Concat concat = new Concat();
		//组成Filelist所需的文件名格式，以逗号分隔。
		StringBuffer sb = new StringBuffer();
		//检查所有文件中最大日期
		File tmp = null;
		long max = 0;
		String path;
		for(String fileName : concatFile.files) {
			path = buildFileName(fileName);
			tmp = new File(path);
			if(tmp.exists()) {
				if(tmp.lastModified() > max) {
					max = tmp.lastModified();
				}
				sb.append(path).append(",");
			} else {
				log("[" + path + "]不存在。", Project.MSG_WARN);
			}
		}
		if(sb.length() > 0) {
			//设置最大的修改时间
			concatFile.setMaxLastModified(max);			
			sb.deleteCharAt(sb.length() - 1);//删除最后的逗号
			
			FileList list = new FileList();
			list.setDir(baseDir);
			list.setFiles(sb.toString());
			concat.addFilelist(list);
			String destFile = concatFile.destfile + "_v" + format.format(new Date(max)) + "." + ext;
			concatFile.setDestfile(destFile);//更新为完整的路径和版本号等，用于生成jsModules用。
			concat.setDestfile(new File(buildFileName(destFile)));
			concat.setForce(false);
			concat.execute();
		} else {
			log(concatFile.destfile + "无需合并的文件。", Project.MSG_WARN);
		}
	}
	
	private String buildFileName(String fileName) {
		return baseDir.getAbsolutePath() + "/" + fileName;
	}
	
	@Root(name="modules")
	public static final class ConfigFile {
		@Element
		private String context;
		@Element
		private String extension;
		@ElementList
		private List<ConcatFile> concats;
		public String getContext() {
			return context;
		}
		public void setContext(String context) {
			this.context = context;
		}
		public String getExtension() {
			return extension;
		}
		public void setExtension(String extension) {
			this.extension = extension;
		}
		public List<ConcatFile> getConcats() {
			return concats;
		}
		public void setConcats(List<ConcatFile> concats) {
			this.concats = concats;
		}
		
	}
	@Root(name="concat")
	public static final class ConcatFile {
		@Element
		private String module;
		@Element
		private String destfile;
		@Element
		private boolean reloadable;
		/**
		 * 最后修改的时间
		 */
		private long maxLastModified;
		@ElementList(name="list", entry="file")
		private List<String> files;
		public String getModule() {
			return module;
		}
		public void setModule(String module) {
			this.module = module;
		}
		public String getDestfile() {
			return destfile;
		}
		public void setDestfile(String destfile) {
			this.destfile = destfile;
		}
		public boolean isReloadable() {
			return reloadable;
		}
		public void setReloadable(boolean reloadable) {
			this.reloadable = reloadable;
		}
		public List<String> getFiles() {
			return files;
		}
		public void setFiles(List<String> files) {
			this.files = files;
		}
		public long getMaxLastModified() {
			return maxLastModified;
		}
		public void setMaxLastModified(long maxLastModified) {
			this.maxLastModified = maxLastModified;
		}
	}
	
	public static void main(String[] args) {
		ResourceConcat rc = new ResourceConcat();
		rc.configFile = "C:\\Personal\\thirdparty\\jQuery\\jquery-1.3.2\\src\\jsfiles.xml";
		rc.baseDir = new File("C:\\Personal\\thirdparty\\jQuery\\jquery-1.3.2\\src");
		rc.execute();
	}

}
